package Client;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class OperatorSelector 
{
	private Double changes_ratio;
	private Integer memory_long;
	private Map<String, Integer> operators_quality;
	private Map<String, List<Integer>> operators_memory;
	private Random rand;

	public OperatorSelector(Double changes_ratio, Integer m_long, String[] operator_names) 
	{
		rand = new Random();
		this.changes_ratio = changes_ratio;
		this.memory_long = m_long;
		operators_memory = new HashMap<String, List<Integer>>();
		operators_quality = new HashMap<String, Integer>();
		for (String s : operator_names)
		{
			operators_memory.put(s, new LinkedList<Integer>());
			for (int i = 0; i < memory_long; i++)
				operators_memory.get(s).add(0);
			operators_quality.put(s, 0);
		}
	}
	
	
	public String selectOperator(Map<String, Double> costs, String operator_name)
	{
		Double old_cost = costs.get(operator_name);
		String best_operator = selectOperatorWithBestCost(costs);
		Double min_cost = costs.get(best_operator);
		
		addBestOperatorInformation(best_operator);
		forgetOperatorsQualities();
		
		String result_operator = operator_name;
		if (changeOperator(operator_name, old_cost, best_operator, min_cost))
			result_operator = best_operator;
	
		
		return result_operator;
	}
	
	private boolean changeOperator(String operator_name, Double old_cost, String best_operator, Double best_cost) 
	{
		if (operator_name.equals(best_operator))
			return false;
		
		Integer a = operators_quality.get(best_operator);
		int b = operators_quality.get(operator_name);
		
		double best_part = a.doubleValue() / memory_long.doubleValue();
		double times_rate = best_part * changes_ratio;
		//Double times_rate = (a.doubleValue() / b.doubleValue()) * (changes_ratio);
		
		//if (b == 0)
		//	times_rate = changes_ratio;
		
		return (rand.nextDouble() < times_rate);
	}


	private String selectOperatorWithBestCost(Map<String, Double> costs)
	{
		String operator_name = (String) costs.keySet().toArray()[0];
		Double min_cost = costs.get(operator_name);
		
		for (String op : costs.keySet())
		{
			if (min_cost > costs.get(op))
			{
				operator_name = op;
				min_cost = costs.get(op);
			}
		}
		
		return operator_name;
	}
	
	private void addBestOperatorInformation(String operator_name)
	{
		for (String s : operators_memory.keySet())
			if (s.equals(operator_name))
				operators_memory.get(s).add(1);
			else
				operators_memory.get(s).add(0);
				
		operators_quality.put(operator_name, operators_quality.get(operator_name) + 1);
	}
	
	private void forgetOperatorsQualities()
	{
		for (String op : operators_memory.keySet())
		{	
			if (operators_memory.get(op).get(0) == 1)
				operators_quality.put(op, operators_quality.get(op) - 1);
			
			operators_memory.get(op).remove(0);
		}
	}
}
